package com.sec.android.app.myfiles.operation.compress;

import android.content.Context;
import android.os.Bundle;

import com.sec.android.app.myfiles.R;
import com.sec.android.app.myfiles.log.Log;
import com.sec.android.app.myfiles.module.abstraction.FileRecord;
import com.sec.android.app.myfiles.operation.FileOperationException;
import com.sec.android.app.myfiles.operation.ProgressListener;

import java.util.ArrayList;

public abstract class AbsCompressorImp {
    public static final String FINAL_DST_PATH = "final_dst_path";

    protected Context mContext;
    protected CompressOptions mOptions;
    protected ProgressListener mCountProgressListener;
    protected ProgressListener mCurFileProgressListener;
    private boolean mIsCancelled;
    protected DuplicatedRecordListener mDuplicatedRecordListener;
    protected Bundle mResultExtras;

    public AbsCompressorImp(Context context, CompressOptions options) {
        mContext = context;
        mOptions = options;
    }

    public void setProgressListener(ProgressListener countProgressListener, ProgressListener curFileProgresslistener) {
        mCountProgressListener = countProgressListener;
        mCurFileProgressListener = curFileProgresslistener;
    }

    public void setDuplicatedRecordListener(DuplicatedRecordListener listener) {
        mDuplicatedRecordListener = listener;
    }

    protected void publishCountProgress(String fileName, int progress, int total) {
        if (mCountProgressListener != null) {
            mCountProgressListener.onProgressChanged(fileName, progress, total);
        }
    }

    protected void publishCurFileProgress(int progress, int total) {
        if (mCurFileProgressListener != null) {
            mCurFileProgressListener.onProgressChanged(null, progress, total);
        }
    }

    protected void publishFinish(boolean bRet, Bundle extras) {
        if (mCountProgressListener != null) {
            mCountProgressListener.onFinished(bRet, null, extras);
        }
    }

    protected FileRecord handleDuplicatedRecord(FileRecord record) {
        if (mDuplicatedRecordListener != null) {
            return mDuplicatedRecordListener.handleDuplicatedRecord(record);
        }
        return null;
    }

    private void prepareResultExtra() {
        if (mResultExtras == null) {
            mResultExtras = new Bundle();
        } else {
            mResultExtras.clear();
        }
    }

    public void cancel() {
        Log.d(this, "cancel");
        mIsCancelled = true;
    }

    public boolean isCancelled() {
        return mIsCancelled;
    }

    public boolean compress(ArrayList<FileRecord> srcList, FileRecord dst) throws FileOperationException {
        boolean ret = _compress(srcList, dst);
        _postOperation(ret, dst);
        return ret;
    }

    public boolean decompress(FileRecord src, FileRecord dst) throws FileOperationException {
        prepareResultExtra();
        boolean ret = _decompress(src, dst);
        publishFinish(ret, mResultExtras);
        _postOperation(ret, dst);
        return ret;
    }

    public boolean decompress(FileRecord src, FileRecord dst, ArrayList<FileRecord> decompressList) throws FileOperationException {
        prepareResultExtra();
        boolean ret = _decompress(src, dst, decompressList);
        publishFinish(ret, mResultExtras);
        _postOperation(ret, dst);
        return ret;
    }

    protected void throwException(int msgResId) throws FileOperationException {
        throw new FileOperationException(mContext.getString(msgResId));
    }

    protected void throwException(int msgResId, Throwable e) throws FileOperationException {
        throw new FileOperationException(mContext.getString(msgResId), e);
    }

    protected void throwException(String msg, Throwable e) throws FileOperationException {
        throw new FileOperationException(msg, e);
    }

    protected void throwCancelException() throws FileOperationException {
        throw new FileOperationException(mContext.getString(R.string.file_operation_cancelled));
    }

    public abstract boolean _compress(ArrayList<FileRecord> srcList, FileRecord dst) throws FileOperationException;

    public abstract boolean _decompress(FileRecord src, FileRecord dst) throws FileOperationException;

    public abstract boolean _decompress(FileRecord src, FileRecord dst, ArrayList<FileRecord> decompressList) throws FileOperationException;

    public abstract CompressedItem[] list(FileRecord src) throws FileOperationException;

    public abstract void _postOperation(boolean result, FileRecord dst);

    public interface DuplicatedRecordListener {
        public FileRecord handleDuplicatedRecord(FileRecord record);
    }

    public static class CompressedItem {
        public String mFullPath;
        public String mPath;
        public String mName;
        public long mSize;
        public long mDate;
        public int mFileType;
        public String mExt;
        public int mChildCount;
        public int mHiddenChildCount;
    }
}
